bool st;
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <vector>
#include <string>
#include <memory>
#include <utility>
#include <iostream>
#include <type_traits>
#include <bits/stdc++.h>

namespace scd
{
    using std::cin, std::cout, std::string, std::vector, std::unique_ptr;
    using std::declval, std::getchar, std::putchar, std::move, std::forward, std::swap, std::endl, std::make_unique;
    using std::is_floating_point, std::is_integral, std::is_reference, std::is_same, std::true_type, std::false_type, std::decay_t, std::enable_if_t, std::size_t;

    template <typename...>
    using void_t = void;

    template <typename T>
    using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;

    template <typename, typename = void>
    struct has_read : false_type
    {
    };

    template <typename T>
    struct has_read<T, void_t<decltype(declval<T &>().read())>> : true_type
    {
    };

    template <typename T>
    inline constexpr bool has_read_v = has_read<T>::value;

    template <typename, typename = void>
    struct has_print : false_type
    {
    };

    template <typename T>
    struct has_print<T, void_t<decltype(declval<T>().print())>> : true_type
    {
    };

    template <typename T>
    inline constexpr bool has_print_v = has_print<T>::value;

    template <typename, typename = void>
    struct is_callable : false_type
    {
    };

    template <typename T>
    struct is_callable<T, void_t<decltype(declval<T>()())>> : true_type
    {
    };

    template <typename T>
    inline constexpr bool is_callable_v = is_callable<T>::value;

    template <typename Raw = int, typename T = decay_t<Raw>>
    inline auto read() -> enable_if_t<is_integral<T>::value, T>
    {
        T x = 0;
        bool fl = false;
        char c = getchar();
        while (c < '0' || c > '9')
            fl |= (c == '-'), c = getchar();
        while (c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + (c ^ 48);
            c = getchar();
        }
        return fl ? -x : x;
    }

    template <typename Raw, typename T = decay_t<Raw>>
    inline auto read() -> enable_if_t<!is_integral<T>::value, T>
    {
        T x;
        cin >> x;
        return x;
    }

    template <typename Raw, typename T = decay_t<Raw>>
    inline auto read(Raw &&x) -> enable_if_t<is_integral<T>::value>
    {
        x = 0;
        bool fl = false;
        char c = getchar();
        while (c < '0' || c > '9')
            fl |= (c == '-'), c = getchar();
        while (c >= '0' && c <= '9')
        {
            x = (x << 3) + (x << 1) + (c ^ 48);
            c = getchar();
        }
    }

    inline void read(char *p)
    {
        char c = getchar();
        while (isspace(c))
            c = getchar();
        while (c != EOF && !isspace(c))
        {
            *p++ = c;
            c = getchar();
        }
        *p = '\0';
    }

    template <typename T>
    inline auto read(T &&x) -> enable_if_t<has_read_v<T>>
    {
        x.read();
    }

    template <typename T>
    inline auto read(T &&x) -> enable_if_t<!is_integral<decay_t<T>>::value &&
                                           !has_read_v<T>>
    {
        cin >> x;
    }

    template <typename... T>
    inline void read(T &&...x)
    {
        (read(forward<T>(x)), ...);
    }

    template <typename Raw = int, typename T = decay_t<Raw>>
    inline auto print(Raw x) -> enable_if_t<is_integral<T>::value>
    {
        if (x < 0)
        {
            putchar('-');
            x = -x;
        }
        if (x > 9)
            print(x / 10);
        putchar(x % 10 + '0');
    }

    template <int d = 6, typename Raw = double, typename T = decay_t<Raw>>
    inline auto print(Raw x) -> enable_if_t<is_floating_point<T>::value>
    {
        printf("%.*f", d, x);
    }

    inline void print(char x)
    {
        putchar(x);
    }

    inline void print(const char *x)
    {
        while (*x)
            putchar(*x++);
    }

    template <typename T>
    inline auto print(T &&x) -> enable_if_t<has_print_v<T>>
    {
        x.print();
    }

    template <typename Raw, typename T = decay_t<Raw>>
    inline auto print(Raw &&x)
        -> enable_if_t<!is_integral<T>::value &&
                       !is_floating_point<T>::value &&
                       !has_print<Raw>::value>
    {
        cout << x;
    }

    template <typename... T>
    inline void print(T &&...x)
    {
        (print(forward<T>(x)), ...);
    }

    template <typename... T>
    inline void printws(T &&...x)
    {
        (print(forward<T>(x), ' '), ...);
    }

    template <typename... T>
    inline void println(T &&...x)
    {
        printws(x...);
        print('\n');
    }

    template <typename T = int>
    class Vec : public vector<T>
    {
    public:
        using vector<T>::vector;

        void read() noexcept
        {
            for (auto &item : *this)
                scd::read(item);
        }

        void print() const noexcept
        {
            for (const auto &item : *this)
                scd::print(item);
        }
    };

    class Str : public string
    {
    public:
        using string::string;

        Str(const string &s) noexcept : string(s) {}

        Str(string &&s) noexcept : string(move(s)) {}

        Str(const char *s) noexcept : string(s) {}

        void read() noexcept { cin >> *this; }

        void print() const noexcept { scd::print(c_str()); }
    };

    // todo! IDIOM copy and swap
    class CowStr
    {
    private:
        Str *s;
        unsigned *cnt;

        void release() noexcept
        {
            if (--*cnt == 0)
            {
                delete s;
                delete cnt;
            }
        }

    public:
        CowStr() noexcept : s(new Str()), cnt(new unsigned(1)) {}

        CowStr(const CowStr &c) noexcept : s(c.s), cnt(c.cnt) { ++*cnt; }

        CowStr(CowStr &&c) noexcept : s(c.s), cnt(c.cnt)
        {
            c.s = nullptr;
            c.cnt = nullptr;
        }

        explicit CowStr(const Str &str) noexcept : s(new Str(str)), cnt(new unsigned(1)) {}
        explicit CowStr(Str &&str) noexcept : s(new Str(move(str))), cnt(new unsigned(1)) {}
        explicit CowStr(const string &str) noexcept : s(new Str(str)), cnt(new unsigned(1)) {}
        explicit CowStr(string &&str) noexcept : s(new Str(move(str))), cnt(new unsigned(1)) {}
        explicit CowStr(const char *str) noexcept : s(new Str(str)), cnt(new unsigned(1)) {}

        CowStr &operator=(CowStr other) noexcept
        {
            swap(*this, other);
            return *this;
        }

        friend void swap(CowStr &a, CowStr &b) noexcept
        {
            swap(a.s, b.s);
            swap(a.cnt, b.cnt);
        }

        ~CowStr() noexcept
        {
            if (cnt)
                release();
        }

        auto &operator[](int i) noexcept { return (*s)[i]; }
        void read() noexcept { s->read(); }
        void print() const noexcept { s->print(); }
    };

    namespace exports
    {
        using scd::print, scd::println, scd::printws, scd::read;
        using scd::Vec, scd::Str, scd::CowStr;
    }
}

using namespace scd::exports;
using namespace std;
constexpr int S = 5e4 + 5, T = 1e3 + 5;
int n, m;
int f[S][T], fb[T];
string s, t;
bool ed;
namespace ns
{
    void decl();
    void main()
    {
        decl();
        exit(0);
        string s, t;
        cin >> s >> t;
        int n = s.size(), m = t.size();
        vector<pair<int, int>> seg;
        for (int i = 0; i + m <= n; ++i)
        {
            bool ok = 1;
            for (int j = 0; j < m; ++j)
            {
                if (s[i + j] != t[j])
                {
                    ok = 0;
                    break;
                }
            }
            if (ok)
                seg.push_back({i, i + m - 1});
        }
        sort(seg.begin(), seg.end(), [](auto &a, auto &b)
             { return a.second < b.second; });
        int del = 0, cur = -1;
        for (auto &x : seg)
        {
            if (x.first > cur)
            {
                del++;
                cur = x.second;
            }
        }
        cout << n - del << "\n";
    }
    namespace impl
    {
        string s, t;
        int n, m;
        int nxt_c[T][26];
        int dp[2][T], nxt[T];
        void main()
        {
            read(s, t);
            n = s.size();
            m = t.size();
            for (auto i = 1, j = 0; i < m; ++i)
            {
                while (j && t[i] != t[j])
                    j = nxt[j - 1];
                if (t[i] == t[j])
                    ++j;
                nxt[i] = j;
            }
            for (auto j = 0; j < m; ++j)
            {
                for (auto c = 0; c < 26; c++)
                {
                    auto k = j;
                    while (k && t[k] != 'a' + c)
                        k = nxt[k - 1];
                    if (t[k] == 'a' + c)
                        k++;
                    nxt_c[j][c] = k;
                }
            }
            memset(dp, -1, sizeof(dp));
            dp[0][0] = 0;
            for (auto i = 0; i < n; ++i)
            {
                auto f = dp[i & 1 ^ 1];
                auto g = dp[i & 1];
                fill(f, f + m, -1);
                for (auto j = 0; j < m; ++j)
                    if (g[j] >= 0)
                    {
                        f[j] = max(f[j], g[j]);
                        auto k = nxt_c[j][s[i] - 'a'];
                        if (k < m)
                            f[k] = max(f[k], g[j] + 1);
                    }
            }
            auto f = dp[n & 1];
            println(*max_element(f, f + m));
        }
    }
    void decl()
    {
        impl::main();
    }
}
int main(int argc, const char **argv)
{
#ifdef _DEBUG
    cerr << (&ed - &st) / 1e6 << endl;
    freopen("//?/I:\\desktop\\down\\data/neck/neck1.in", "r", stdin);
#else
    freopen("neck.in", "r", stdin);
    freopen("neck.out", "w", stdout);
#endif
    ns ::main();
    return 0;
    read(s, t);
    n = s.size();
    m = t.size();
    s = ' ' + s;
    t = ' ' + t;
    fb[1] = 1;
    for (int i = 2, j = 1; i <= m; ++i)
    {
        while (j != 1 && t[i] != t[j])
            j = fb[j];
        if (t[i] == t[j])
            ++j;
        fb[i] = j;
    }
    vector<pair<int, int>> segs;
    // for (int i = 1, j = 1; i <= n; ++i)
    // {
    //     while (j != 1 && s[i] != t[j])
    //         j = fb[j];
    //     if (s[i] == t[j])
    //         ++j;
    //     segs.push_back({j, i});
    // }
    for (int i = 1; i + m - 1 <= n; ++i)
    {
        bool ok = 1;
        for (int j = 1; j <= m; ++j)
        {
            if (s[i + j - 1] != t[j])
            {
                ok = 0;
                break;
            }
        }
        if (ok)
            segs.push_back({i, i + m - 1});
    }
    sort(begin(segs), end(segs), [](const pair<int, int> &a, const pair<int, int> &b)
         { return a.second < b.second; });
    int rm = 0;
    int p = 0;
    for (const auto &[l, r] : segs)
        if (p < l)
        {
            ++rm;
            p = r;
        }
    println(n - rm);
    /*
    f[0][0] = n;
    for (int i = 0; i < n; ++i)
    {
        int lim = min(i, m - 1);
        for (int j = 0; j <= lim; ++j)
        {
            int k = j;
            while (k && s[i] != t[k])
                k = fb[k];
            if (k == m)
                f[i + 1][k] = max(f[i + 1][k], f[i][j] - 1);
            else
                f[i + 1][k + 1] = max(f[i + 1][k + 1], f[i][j]);
        }
    }
    println(*max_element(f[n], f[n] + m));
    */
    return 0;
}
